package gbase

import (
	"fmt"
	"reflect"
	"runtime/debug"

	"github.com/cloudwego/hertz/pkg/common/hlog"
)

//支持格式化 param:string/err/format
/*
- Panic("simple message") - 直接panic字符串
- Panic(err) - panic错误信息
- Panic("format %s", "string") - 支持格式化字符串
- Panic(123) - 自动转换为字符串
*/
func Panic(param ...any) {
	if len(param) == 0 {
		panic(EServer())
	}

	// 处理格式化字符串情况
	if len(param) > 1 {
		if format, ok := param[0].(string); ok {
			panic(fmt.Sprintf(format, param[1:]...))
		}
	}

	// 原有逻辑
	switch param[0].(type) {
	case string:
		panic(param[0].(string))
	case error:
		panic(param[0].(error).Error())
	default:
		panic(fmt.Sprint(param[0]))
	}
}

func Recover() {
	if r := recover(); r != nil {
		hlog.Errorf("recover from panic:%v\n%s", r, debug.Stack())
	}
}

// PanicRecover 包装任意函数调用，捕获可能的 panic
// 原始版本只支持 func() 类型的函数
func PanicRecover(fn func()) {
	defer func() {
		if r := recover(); r != nil {
			hlog.Errorf("recover from panic:%v\n%s", r, debug.Stack())
		}
	}()

	// 可能导致 panic 的操作
	fn()
}

// PanicRecoverFunc 通用版本，支持任意类型的函数
// 返回与输入函数相同签名的新函数，但会捕获 panic
// 示例用法：
//
//	safeFn := PanicRecoverFunc(func(a, b int) int {
//	   return a / b  // 可能会因除零而 panic
//	})
//
// safeFn.(func(int, int) int)(10, 0)  // 不会导致 panic
func PanicRecoverFunc(fn interface{}) interface{} {
	// 获取函数的反射值
	v := reflect.ValueOf(fn)
	// 检查是否为函数
	if v.Kind() != reflect.Func {
		panic("PanicRecoverFunc: 参数必须是函数")
	}

	// 获取函数类型
	t := v.Type()

	// 创建一个与原函数相同签名的新函数
	wrapped := reflect.MakeFunc(t, func(args []reflect.Value) (results []reflect.Value) {
		// 设置默认返回值（如果原函数有返回值）
		results = make([]reflect.Value, t.NumOut())
		for i := 0; i < t.NumOut(); i++ {
			results[i] = reflect.Zero(t.Out(i))
		}

		// 使用 defer-recover 捕获可能的 panic
		defer func() {
			if r := recover(); r != nil {
				hlog.Errorf("recover from panic:%v\n%s", r, debug.Stack())
				// 返回零值结果
				return
			}
		}()

		// 调用原始函数
		return v.Call(args)
	})

	// 返回包装后的函数
	return wrapped.Interface()
}

// PanicRecoverAny 简化版，适用于常见场景
// 示例用法：
//
//	PanicRecoverAny(func(a, b int) int {
//	   return a / b  // 可能会因除零而 panic
//	}, 10, 0)  // 会安全地捕获 panic
func PanicRecoverAny(fn interface{}, args ...interface{}) (result []interface{}, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("函数执行 panic: %v", r)
			hlog.Errorf("recover from panic:%v\n%s", r, debug.Stack())
		}
	}()

	// 获取函数的反射值
	v := reflect.ValueOf(fn)
	// 检查是否为函数
	if v.Kind() != reflect.Func {
		return nil, fmt.Errorf("PanicRecoverAny: 第一个参数必须是函数")
	}

	// 准备参数
	vargs := make([]reflect.Value, len(args))
	for i, arg := range args {
		vargs[i] = reflect.ValueOf(arg)
	}

	// 调用函数
	res := v.Call(vargs)

	// 转换返回值
	result = make([]interface{}, len(res))
	for i, r := range res {
		result[i] = r.Interface()
	}

	return result, nil
}

func Go(fn func()) {
	go func() {
		PanicRecover(fn)
	}()
}
